- catalina.out过大的定位过程&解决方案
场景记录
在一次mysql create table失败问题定位过程中,发现exitcode是28,即磁盘写失败导致的。可以参见这里,df -hk
的查看结果是mysql所在分区100%usage。
问题定位过程
找到大文件
首先需要找到问题原因,即被什么文件吃满了disk。
du -sh / | sort -h
一直分析下去,可以定位到原因是catalina.out & flume的log比较大。
什么内容写入到catalina.out
catalina.out文件是tomcat的默认log方式,采用的是java.util.logging.Logging来控制的。其配置文件是:
[root@test-239 logs]# ps aux | grep java | grep logging
root 27130 0.9 12.4 4780116 998124 ? Sl 04:01 4:42 java -Djava.util.logging.config.file=/usr/local/ahiddenpath/apache-tomcat-7.0.64/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.security.egd=file:/dev/./urandom -Djava.endorsed.dirs=/usr/local/ahiddenpath/apache-tomcat-7.0.64/endorsed -classpath /usr/local/ahiddenpath/apache-tomcat-7.0.64/bin/bootstrap.jar:/usr/local/ahiddenpath/apache-tomcat-7.0.64/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/ahiddenpath/apache-tomcat-7.0.64 -Dcatalina.home=/usr/local/ahiddenpath/apache-tomcat-7.0.64 -Djava.io.tmpdir=/usr/local/ahiddenpath/apache-tomcat-7.0.64/temp org.apache.catalina.startup.Bootstrap start
据上可知,配置文件在/usr/local/ahiddenpath/apache-tomcat-7.0.64/conf/logging.properties
,查看其中内容:
handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
其中:
- FileHandler:输出log到指定文件
- ConsoleHandler:输出log到console
在写demo验证logging.properties配置项的时候发现:
- java project默认是使用jre lib中的配置
- path一般是jre/lib下面的logging.properties
这个确实比较坑,改了半天配置都不生效,具体可以戳这里
另外一个比较蠢萌的点,是
-Djava.util.logging.config.file
指定logging.properties位置的时候,-D需要在被运行的类之前,如:
- 这样是对的:java -Dxxx class
- 这样是无效的:java class -Dxxx
除了catalina.out,tomcat还有什么其他日志
在看到文章:
- tomcat的几种log&version=12020810&nettype=WIFI&fontScale=100&pass_ticket=K7dxD3itvEIhOesfQoiCKNkkYFtbi28AIxNOKygQiPmzPpMpvzio45mY5vliTrfm)
- tomcat 官方文档(6.0)关于日志的配置
- oracle LogManager 类 API 文档
之后,对其中提到的 tomcat 的几种 log 做个总结:
- log 类型是
- catalina.out
- cataliana.{yyyy-MM-dd}.log
- localhost.{yyyy-MM-dd}.log
- manager.{yyyy-MM-dd}.log
- host-manager.{yyyy-MM-dd}.log
- tomcat 可以改用log4j
- console的内容会输出到 catalina.out,即
System.out.println()
。
更多的详细信息还是参见上面的三篇文档。
如何解决问题
为了避免这个问题,两种思路去限制:
- 修改配置本身不输出到catalina.out
- 限制catalina.out的输出:log rotate
log rotate
- 这个文不错
- https://support.rackspace.com/how-to/sample-logrotate-configuration-and-troubleshooting/
- 但修改了old folder之后,测试失败了,不知为何
是由cron触发的,定期执行的log切分程序。与log4j的文件拆分是有区别的,比如无法设置文件大小上限。
具体学习的话,可以参考文档:
- logrotate的机制与原理
- 戳这里
- 核心内容:
- cron触发:
/etc/cron.daily/logrotate
- 自定义在/etc/logrotate下面的conf,是通过/etc/logrotate.conf中的
include /etc/logrotate.d
来触发的 - 另外文中还比较了create和copytruncate方案的原理
- cron触发:
- log rotate sample
修改logging配置文件
很简单,删除 ${catalina.base}/conf下面的logging.properties中的handlers= java.util.logging.ConsoleHandler
即可。
这里举例是针对tomcat默认的logging.properties的位置,具体到其他项目,请具体查看
-Djava.util.logging.config.file
的值
通过简单代码例子可知:
测试类代码:
package demo.maven;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* java util logging的测试类.
* @author liruifeng
* @see JavaUtilLoggingTest
*/
public class JavaUtilLoggingTest {
private static final Logger logger = Logger.getLogger(JavaUtilLoggingTest.class.getName());
public static void main(String args[]) {
System.out.println(System.getProperty("java.util.logging.config.file"));
System.out.println(System.getProperty("sss"));
// Handler consoleHandler = new ConsoleHandler();
// consoleHandler.setLevel(Level.ALL);
// Logger.getAnonymousLogger().addHandler(consoleHandler);
logger.setLevel(Level.ALL);
System.out.println(logger.getLevel());
logger.log(Level.ALL, "Level.ALL");
logger.log(Level.FINE, "Level.FINE");
logger.fine("fine");
logger.log(Level.FINER, "Level.FINER");
logger.log(Level.FINEST, "Level.FINEST");
logger.log(Level.CONFIG, "Level.CONFIG");
logger.log(Level.INFO, "Level.INFO");
logger.info("info");
logger.log(Level.WARNING, "Level.WARNING");
logger.log(Level.SEVERE, "Level.SEVERE");
logger.log(Level.OFF, "Level.OFF");
}
}
原logging.properties(部分,在$jre_path/lib下面):
handlers=java.util.logging.ConsoleHandler
output:
null
null
ALL
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
全部: Level.ALL
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
详细: Level.FINE
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
详细: fine
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
较详细: Level.FINER
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
非常详细: Level.FINEST
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
配置: Level.CONFIG
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
信息: Level.INFO
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
信息: info
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
警告: Level.WARNING
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
严重: Level.SEVERE
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
禁用: Level.OFF
修改后的logging.properties
#handlers=java.util.logging.ConsoleHandler
对应output:
null
null
ALL
以上,测试生效